package oss

import (
	"encoding/json"
	"fmt"
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/duke-git/lancet/v2/cryptor"
	"github.com/duke-git/lancet/v2/fileutil"
	"github.com/ncruces/zenity"
	"log/slog"
	"video2m3u8/layouts"
	"video2m3u8/logging"
)

type Config struct {
	AccessKey  string `json:"accessKey"` // 访问密钥ID
	SecretKey  string `json:"secretKey"`
	BucketName string `json:"bucketName"`
	EndPoint   string `json:"region"`
	Domain     string `json:"domain"`
	BasePath   string `json:"basePath"`
}

// 存储已打开窗口的映射表
var ossSettingWinMap = make(map[string]fyne.Window)
var settingTitle = "设置OSS"
var fileUrlTitle = "视频地址"
var ossClient *oss.Client

const configFile = "config.data"
const configSecretKey = "8ew901329djus8dj"

// ReadOssConfig 从配置文件中读取OSS配置
func ReadOssConfig() Config {
	//从指定目录读取json文件
	if !fileutil.IsExist(configFile) {
		fileutil.CreateFile(configFile)
	}
	data, _ := fileutil.ReadFileToString(configFile)
	if data != "" {
		decrypted := cryptor.AesCbcDecrypt([]byte(data), []byte(configSecretKey))
		conf := Config{}
		err := json.Unmarshal(decrypted, &conf)
		if err != nil {
			slog.Error("读取配置文件失败", "err", err)
			logging.LogChan <- fmt.Sprintf("读取配置文件失败: %v", err)
			return Config{}
		}
		return conf
	}
	return Config{}
}

// SettingOss 设置OSS
func SettingOss(a fyne.App, parent fyne.Window) {
	if _, ok := ossSettingWinMap[settingTitle]; ok {
		ossSettingWinMap[settingTitle].Show()
		return
	}
	ossSettingWin := a.NewWindow(settingTitle)
	ossSettingWin.SetOnClosed(func() {
		delete(ossSettingWinMap, settingTitle)
	})
	ossSettingWin.Resize(fyne.NewSize(400, 0))
	ossSettingWin.SetContent(NewOssSettingWindow())
	ossSettingWin.Show()
	ossSettingWinMap[settingTitle] = ossSettingWin
}
func SettingFileUrlShow(url string) {
	if _, ok := ossSettingWinMap[fileUrlTitle]; ok {
		ossSettingWinMap[fileUrlTitle].Show()
		return
	}
	ossUrlWin := layouts.App.NewWindow(fileUrlTitle)
	ossUrlWin.SetOnClosed(func() {
		delete(ossSettingWinMap, fileUrlTitle)
	})
	label := widget.NewLabel(fmt.Sprintf("%s", url))
	ossUrlWin.SetContent(container.NewVBox(
		container.NewHBox(label, widget.NewButton("复制", func() {
			layouts.TopWindow.Clipboard().SetContent(label.Text)
		}))))
	ossUrlWin.Show()
}

func NewOssSettingWindow() fyne.CanvasObject {
	conf := ReadOssConfig()
	//密钥Id
	accessKey := widget.NewEntry()
	accessKey.SetText(conf.AccessKey)
	accessKey.SetPlaceHolder("请输入AccessKey")
	//SecretKey
	secretKey := widget.NewEntry()
	secretKey.SetText(conf.SecretKey)
	secretKey.SetPlaceHolder("请输入SecretKey")
	bucketName := widget.NewEntry()
	bucketName.SetText(conf.BucketName)
	bucketName.SetPlaceHolder("请输入BucketName")
	endPoint := widget.NewEntry()
	endPoint.SetText(conf.EndPoint)
	endPoint.SetPlaceHolder("请输入EndPoint")
	basePath := widget.NewEntry()
	basePath.SetText(conf.BasePath)
	basePath.SetPlaceHolder("请输入BasePath")
	domain := widget.NewEntry()
	domain.SetText(conf.Domain)
	domain.SetPlaceHolder("请输入Domain")
	//构建表单
	form := widget.NewForm(
		widget.NewFormItem("AccessKey", accessKey),
		widget.NewFormItem("SecretKey", secretKey),
		widget.NewFormItem("BucketName", bucketName),
		widget.NewFormItem("EndPoint", endPoint),
		widget.NewFormItem("BasePath", basePath),
		widget.NewFormItem("Domain", domain),
	)
	//保存
	saveBtn := widget.NewButton("保存", func() {
		//条件判断
		if accessKey.Text == "" ||
			secretKey.Text == "" ||
			bucketName.Text == "" ||
			endPoint.Text == "" ||
			basePath.Text == "" ||
			domain.Text == "" {
			logging.LogChan <- fmt.Sprintf("请填写完整配置信息")
			return
		}
		conf := Config{
			AccessKey:  accessKey.Text,
			SecretKey:  secretKey.Text,
			BucketName: bucketName.Text,
			EndPoint:   endPoint.Text,
			BasePath:   basePath.Text,
			Domain:     domain.Text,
		}
		re := submitSave(conf)
		if re {
			if _, ok := ossSettingWinMap[settingTitle]; ok {
				ossSettingWinMap[settingTitle].Close()
			}
		}
	})
	//返回边框
	return container.NewVBox(
		form,
		saveBtn,
	)
}
func GetOssClient(conf Config) (*oss.Client, *oss.Bucket, error) {
	if conf.AccessKey == "" || conf.SecretKey == "" {
		return nil, nil, fmt.Errorf("请填写完整OSS配置信息")
	}
	var buket *oss.Bucket
	if ossClient == nil {
		//验证oss 配置是否正确
		client, err := oss.New(conf.EndPoint, conf.AccessKey, conf.SecretKey)
		if err != nil {
			logging.LogChan <- fmt.Sprintf("验证OSS配置失败: %v", err)
			return nil, nil, err
		}
		_, err = client.GetBucketCname(conf.BucketName)
		if err != nil {
			logging.LogChan <- fmt.Sprintf("验证OSS配置BucketName: %v", err)
			err := client.CreateBucket(conf.BucketName)
			if err != nil {
				logging.LogChan <- fmt.Sprintf("验证OSS配置创建BucketName失败: %v", err)
				return nil, nil, err
			} else {
				logging.LogChan <- fmt.Sprintf("验证OSS配置创建BucketName[%s]成功", conf.BucketName)
			}
		}
		ossClient = client
	}
	buket, err := ossClient.Bucket(conf.BucketName)
	if err != nil {
		logging.LogChan <- fmt.Sprintf("验证OSS配置获取桶实例失败: %v", err)
		return nil, nil, err
	}
	return ossClient, buket, nil
}

func submitSave(conf Config) bool {
	_, _, err := GetOssClient(conf)
	if err != nil {
		zenity.Error(err.Error(), zenity.Title("OSS配置错误"))
		return false
	}
	bytes, err := json.Marshal(conf)
	if err != nil {
		logging.LogChan <- fmt.Sprintf("序列化配置文件失败: %v", err)
		return false
	}
	err = fileutil.WriteBytesToFile(configFile, cryptor.AesCbcEncrypt(bytes, []byte(configSecretKey)))
	if err != nil {
		logging.LogChan <- fmt.Sprintf("保存配置文件失败: %v", err)
		return false
	}
	logging.LogChan <- fmt.Sprintf("保存OSS配置文件成功")
	return true
}
